﻿// <copyright file="FFTModuleView.xaml.cs" company="Waveform Lab.NET">
// Signal processing by PC oscilloscope
// http://waveformlab.codeplex.com/
//
// Copyright (c) 2011 Waveform Lab.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
using System.IO;
using System.Numerics;
using MathNet.Numerics;
using MathNet.Numerics.IntegralTransforms;
using MathNet.Numerics.Signals;
using PluginModule.Core;


namespace FFTModule
{
    /// <summary>
    /// Interaction logic for FFTModuleView.xaml
    /// </summary>
    [Export(typeof(IPlugin))]
    [ExportMetadata("ModuleName", "FFTModule")]
    [ExportMetadata("ModuleId", 2)] 
    public partial class FFTModuleView : UserControl,IPlugin
    {
        private string _filename;
        private string _name_x = "Power";
        private string _name_y = "Frequency [Hz]";
        private double _nyquistrate = 0.0;
        public int _actualsamplingnumber = 0;

        public FFTModuleView()
        {
            InitializeComponent();
        }

        public string ModuleName
        {
            get { return "FFTModule"; }
        }

        public bool Captured
        {
            get { return false; }
            set { }
        }

        public bool EnableLeft
        {
            get { return false; }
        }

        public bool EnableRight
        {
            get { return false; }
        }

        public uint BufferNo
        {
            get { return 0; }
        }

        public string FileName
        {
            get { return _filename; }
        }

        public string NameX
        {
            get { return _name_x; }
        }

        public string NameY
        {
            get { return _name_y; }
        }

        public double SampleRate
        {
            get { return 0.0; }
        }

        public int SampleNumber
        {
            get { return 0; }
        }

        public double NyquistRate
        {
            get { return _nyquistrate; }
            set { _nyquistrate = value; }
        }

        public int ActualSamplingNumber
        {
            get { return _actualsamplingnumber;}
            set { _nyquistrate = value; }
        }

        private double resolution = 0.0;

        public string Processing(string l, string r, bool ch1, bool ch2)
        {
            string msg = string.Empty;

            if (ch1 && radioButtonCh1.IsChecked == true)
            {
                float[] real1 = ReadCSV(l);
                double[] fft1 = FFT(real1);
                _actualsamplingnumber = fft1.Length;
                resolution = _nyquistrate / _actualsamplingnumber;
                _filename = WriteCSV_fft(l, "CH1", fft1);
                msg += "CH1: FFT " + real1.Length.ToString() + "\n";
            }
            if (ch2 && radioButtonCh2.IsChecked == true)
            {
                float[] real2 = ReadCSV(r);
                double[] fft2 = FFT(real2);
                _actualsamplingnumber = fft2.Length;
                resolution = _nyquistrate / _actualsamplingnumber;
                _filename = WriteCSV_fft(r, "CH2", fft2);
                msg += "CH2: FFT " + real2.Length.ToString()+"\n";
            }

            labelNyquistRate.Text = _nyquistrate.ToString();
            labelSamplingNumber.Text = _actualsamplingnumber.ToString();
            labelResolution.Text = resolution.ToString();

            return msg;
        }

        private double[] FFT(float[] real)
        {
            int length = real.Length;
            if (length == 0) return null;

            System.Numerics.Complex[] data = new System.Numerics.Complex[length];

            for (int i = 0; i < length; i++)
                data[i] = new System.Numerics.Complex(real[i], 0);

            MathNet.Numerics.IntegralTransforms.Transform.FourierForward(data, FourierOptions.Matlab);
            //MathNet.Numerics.IntegralTransforms.Transform.FourierInverse(data, FourierOptions.Matlab); 

            length = data.Length/2;
            if (length == 0) return null;
            double[] fft_real = new double[length];
            for (int i = 0; i < length; i++)
                //fft_real[i] = data[i].Magnitude;
                fft_real[i] = Math.Pow(data[i].Magnitude, 2);
                //fft_real[i] = 10 * Math.Log10(data[i].Magnitude);
                //fft_real[i] = 20*Math.Log10(Math.Pow(data[i].Magnitude,2));

            return fft_real;
        }


        private float[] ReadCSV(string name)
        {
            using (StreamReader csv_reader = new StreamReader(name))
            {
                int cnt = 0;
                while (!csv_reader.EndOfStream)
                {
                    string s = csv_reader.ReadLine();
                    try
                    {
                        float v = float.Parse(s);
                        cnt++;
                    }
                    catch { }
                }
                float[] dat = new float[cnt];
                int n = 0;
                csv_reader.Close();

                using (StreamReader csv_reader2 = new StreamReader(name))
                {
                    while (!csv_reader2.EndOfStream)
                    {
                        string s = csv_reader2.ReadLine();
                        float v = 0.0f;
                        try
                        {
                            v = float.Parse(s);
                        }
                        catch { }
                        dat[n++] = v;
                    }
                    csv_reader2.Close();

                    return dat;
                }
            }
        }


        private string WriteCSV_fft(string name, string ch, double[] fft)
        {
            string file = name + "_fft" +ch +".csv";
            using(StreamWriter csv_writer = new StreamWriter(file))
            {
                csv_writer.WriteLine("FFT," + ch.ToString());
                int i = 0;
                foreach (double x in fft)
                {
                    csv_writer.WriteLine((i * resolution).ToString() + "," + x.ToString());
                    i++;
                }
                csv_writer.Close();
            }

            return file;
        }

    }
}
